#ifndef UTIL_LOGGER_H
#define UTIL_LOGGER_H

#include <atomic>
#include <condition_variable>
#include <memory>
#include <mutex>
#include <thread>
#include <string>
#include <vector>
#include <ctime>
#include <cstdio>
#include <unistd.h>

namespace util {

/**
 * @brief 日志级别枚举
 * 
 * 定义不同的日志级别，用于控制日志输出的详细程度
 * 使用 enum class 更加安全和强类型化，可以避免名称冲突和意外的隐式转换。
 */
enum class LogLevel {
    TRACE,  // 最详细的日志，用于调试
    DEBUG,  // 调试信息，开发阶段使用
    INFO,   // 普通信息，记录系统运行状态
    WARN,   // 警告信息，可能存在问题但不影响系统运行
    ERROR,  // 错误信息，发生可恢复的错误
    FATAL   // 致命错误，导致系统无法正常运行
};

/**
 * @brief 日志缓冲区类
 * 
 * 实现一个固定大小的缓冲区，用于暂存日志数据，减少IO次数
 */
class LogBuffer {
public:
    /**
     * @brief 构造函数
     * @param size 缓冲区大小（字节）
     */
    explicit LogBuffer(size_t size);

    /**
     * @brief 析构函数
     */
    ~LogBuffer();

    /**
     * @brief 向缓冲区追加数据
     * @param data 数据指针
     * @param len 数据长度
     * @return 是否成功追加（若缓冲区已满则失败）
     */
    bool append(const char* data, size_t len);
    
    /**
     * @brief 重置缓冲区
     */
    void reset() { _current = _data; }

    /**
     * @brief 缓冲区剩余空间
     */
    size_t avail() const { return _capacity - length(); }
    
    /**
     * @brief 获取当前已使用的缓冲区长度
     * @return 已使用长度（字节）
     */
    size_t length() const { return _current - _data; }
    
    /**
     * @brief 获取缓冲区起始地址
     */
    const char* data() const { return _data; }
    
    // 
    /**
     * @brief 判断缓冲区是否已满
     */
    bool full() const { return length() >= _capacity; }

private:
    char* _data;           // 缓冲区内存
    size_t _capacity;      // 缓冲区容量
    char* _current;        // 当前写入位置
};

/**
 * @brief 双缓冲日志系统
 * 
 * 使用双缓冲技术实现高性能异步日志，减少IO操作对业务线程的影响
 */
class AsyncLogging {
public:
    /**
     * @brief 构造函数
     * @param basename 日志文件名前缀
     * @param rollSize 日志文件滚动大小（字节）
     * @param flushInterval 自动刷新间隔（秒）
     */
    explicit AsyncLogging(const std::string& basename, 
                         size_t rollSize = 1024*1024*50,  // 50MB
                         int flushInterval = 3);          // 3秒刷盘一次

    /**
     * @brief 析构函数
     */
    ~AsyncLogging();
    
    /**
     * @brief 启动日志线程
     */
    void start();
    
    /**
     * @brief 停止日志线程
     */
    void stop();
    
    /**
     * @brief 追加日志内容（前端接口，无锁操作）
     * @param logline 日志内容指针
     * @param len 日志内容长度
     */
    void append(const char* logline, int len);

    /**
     * @brief 强制刷新所有缓冲区到磁盘
     * 
     * 阻塞调用线程，直到所有已提交的日志都写入磁盘
     */
    void forceFlush();

private:
    /**
     * @brief 后端线程函数（负责将日志写入文件）
     */
    void threadFunc();
    
    using Buffer = LogBuffer;
    using BufferPtr = std::unique_ptr<Buffer>;
    using BufferVector = std::vector<BufferPtr>;
    
    const std::string _basename;      // 日志文件名前缀
    const size_t _rollSize;           // 日志文件滚动大小
    const int _flushInterval;         // 刷盘间隔（秒）
    
    std::atomic<bool> _running;       // 运行状态
    std::thread _thread;              // 后端线程
    std::mutex _mutex;                // 互斥锁
    std::condition_variable _cond;    // 条件变量
    
    BufferPtr _currentBuffer;         // 当前写入缓冲区
    BufferPtr _nextBuffer;            // 预备缓冲区
    BufferVector _buffers;            // 待刷盘的缓冲区队列

    std::condition_variable _flushCond;  // 刷新条件变量
    std::atomic<bool> _flushRequest;     // 刷新请求标志
};

/**
 * @brief 日志管理器（单例模式）
 * 
 * 提供统一的日志接口，管理日志系统的初始化和使用
 */
class Logger {
public:
    /**
     * @brief 获取单例实例
     * @return 日志管理器实例引用
     */
    static Logger& instance();
    
    /**
     * @brief 初始化日志系统
     * @param basename 日志文件名前缀
     * @param rollSize 日志文件滚动大小
     * @param flushInterval 自动刷新间隔
     */
    void init(const std::string& basename, 
             size_t rollSize = 1024*1024*50,
             int flushInterval = 3);
    
    /**
     * @brief 记录日志
     * @param level 日志级别
     * @param file 文件名
     * @param line 行号
     * @param func 函数名
     * @param format 格式化字符串
     */
    void log(LogLevel level, const char* file, int line, const char* func, const char* format, ...);
    
    /**
     * @brief 强制刷新日志缓冲区
     *
     * 确保所有已记录的日志都写入磁盘，通常在关键操作前后使用
     */
    void flush();

    /**
     * @brief 获取当前日志级别
     * @return 当前日志级别
     */
    LogLevel level() const { return _level; }

    /**
     * @brief 设置日志级别
     * @param level 新的日志级别
     */
    void setLevel(LogLevel level) { _level = level; }

    /**
     * @brief 关闭日志系统
     */
    void shutdown();

private:
    Logger();
    ~Logger();
    
    // 禁止拷贝
    Logger(const Logger&) = delete;
    Logger& operator=(const Logger&) = delete;
    
    std::unique_ptr<AsyncLogging> _asyncLogger;
    LogLevel _level;
};

} // namespace util

// 日志宏定义（方便使用）
#define LOG_TRACE(...) \
    if (util::LogLevel::TRACE >= util::Logger::instance().level()) \
        util::Logger::instance().log(util::LogLevel::TRACE, __FILE__, __LINE__, __FUNCTION__, __VA_ARGS__)

#define LOG_DEBUG(...) \
    if (util::LogLevel::DEBUG >= util::Logger::instance().level()) \
        util::Logger::instance().log(util::LogLevel::DEBUG, __FILE__, __LINE__, __FUNCTION__, __VA_ARGS__)

#define LOG_INFO(...) \
    if (util::LogLevel::INFO >= util::Logger::instance().level()) \
        util::Logger::instance().log(util::LogLevel::INFO, __FILE__, __LINE__, __FUNCTION__, __VA_ARGS__)

#define LOG_WARN(...) \
    if (util::LogLevel::WARN >= util::Logger::instance().level()) \
        util::Logger::instance().log(util::LogLevel::WARN, __FILE__, __LINE__, __FUNCTION__, __VA_ARGS__)

#define LOG_ERROR(...) \
    if (util::LogLevel::ERROR >= util::Logger::instance().level()) \
        util::Logger::instance().log(util::LogLevel::ERROR, __FILE__, __LINE__, __FUNCTION__, __VA_ARGS__)

#define LOG_FATAL(...) \
    if (util::LogLevel::FATAL >= util::Logger::instance().level()) \
        util::Logger::instance().log(util::LogLevel::FATAL, __FILE__, __LINE__, __FUNCTION__, __VA_ARGS__)

/**
 * @brief 强制刷新所有日志到磁盘
 * 
 * 确保所有已记录的日志都写入磁盘，通常在关键操作前后使用
 */
#define LOG_FLUSH() \
    util::Logger::instance().flush()

#endif // UTIL_LOGGER_H